﻿using System;
using System.Collections;
using System.IO;
using HtmlAgilityPack;
using System.Web.UI;

namespace CSharp.Libs.Net
{
    /// <summary>
    /// generates a html file containing clickable links
    /// </summary>
    public class HtmlLinkPageGenerator : IDisposable
    {
        #region declarations
        string _strResult = "";
        #endregion



        #region constructor
        public HtmlLinkPageGenerator()
        {
        }
        public HtmlLinkPageGenerator(ArrayList StringListWithLinks)
        {
            LinkList = StringListWithLinks;
        }

        #region dispose pattern (http://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P)
        // some fields that require cleanup
        private bool disposed = false; // to detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // clean up managed handles here
                    LinkList = null;
                }

                disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
        #endregion
        #endregion



        #region private functions
        /// <summary>
        /// function that actually does the work :)
        /// </summary>
        private void _outputFile()
        {
            //check error conditions
            if (LinkList == null) { throw new ArgumentNullException("LinkList is null"); } //no link list is given
            if (LinkList.Count == 0) { throw new ArgumentException("LinkList is empty"); } //link list is empty
            if (string.IsNullOrEmpty(FileName)) { throw new ArgumentException("No file name given"); } //no destination file is given
            if (File.Exists(FileName)) { throw new ArgumentException("File already exists"); } //destination file exists
            if (!File.Exists(HtmlStubFileName)) { throw new FileNotFoundException("File not found"); } //html stub does not exist

            //create HtmlDocument object
            HtmlDocument hd = new HtmlDocument();
            hd.Load(HtmlStubFileName); //load stub

            //get body 
            HtmlNode ndBody = hd.DocumentNode.SelectSingleNode("//body");
            if (ndBody == null) { throw new InvalidDataException("No body found in stub"); } //no body is found

            //cycle through linklist
            foreach (string strLink in LinkList)
            {
                //create surrounding div for each link
                HtmlNode ndDiv = hd.CreateElement("div");
                ndDiv.Attributes.Append(hd.CreateAttribute("class", "Link"));

                //create anchor of each link including itself as text
                HtmlNode ndA = hd.CreateElement("a");
                ndA.Attributes.Append(hd.CreateAttribute("href", strLink));
                ndA.InnerHtml = strLink;

                //append anchor to div and div to body
                ndDiv.AppendChild(ndA);
                ndBody.AppendChild(ndDiv);
            }

            //save resulting document to destination filename
            hd.Save(FileName);

            //put resulting document to result string
            using (StringWriter sw = new StringWriter())
            {
                hd.Save(sw);
                _strResult = sw.ToString();
            }            
        }
        #endregion



        #region properties
        /// <summary>
        /// contains all links as string
        /// </summary>
        public ArrayList LinkList { get; set; }

        /// <summary>
        /// can be read after OutputString() was called and has finished
        /// </summary>
        public string Result { get { return _strResult; } }

        /// <summary>
        /// to save output to
        /// </summary>
        public string FileName { get; set; }

        /// <summary>
        /// stub to add linklist to
        /// </summary>
        public string HtmlStubFileName { get; set; }
        #endregion



        #region methods
        /// <summary>
        /// creates a file containing the generated html code using a stub file which contains a basic wellformed head and body
        /// </summary>
        /// <remarks>
        /// It's necessary to supply the LinkList, the HtmlStubFileName and the FileName. The FileName may not exist. Nothing will be overwritten.
        /// </remarks>
        public void OutputFile()
        {
            _outputFile();
        }
        #endregion
    }
}
